/*
 * locks.h
 *
 *  Created on: Jun 4, 2011
 *      Author: peckb1
 */

#ifndef LOCKS_H_
#define LOCKS_H_

#include "synch.h"
#include "sharedDefinitions.h"
#include "item.h"

class Locks {
public:
	int testNo;
	int t1_selectedLines[MAXIMUM_OCCUPANCY];
	Lock* t1_l1;
	Condition* t1_c1;
	int t1_numberOfCustomersReadyToGetIntLines;
	Semaphore* t1_done; // So that TestSuite knows when Test 1 is
	                    // done


    Item* itemsInStore[MAX_ITEMS];
    double totalStoreSales;
    double registerSales[MAX_CLERKS];
    /*
     * Monitor section for the Item-Stockboy/Customer interaction
     */
    Lock* _shelfLock[MAX_ITEMS];
    Condition* _itemWaitCV[MAX_ITEMS];
    int _itemStockOnShelf[MAX_ITEMS];
    Lock* _customerWaitingForReStockLock;
    int _stockBoyReStockingItem[MAX_ITEMS];
    int _customersWaitingForRestock[MAX_ITEMS]; //Initial values set to zero
    /*
     * Lock for StockBoy-StockRoom interaction
     * Used by stockboys
     */
    Lock* _stockRoomStatusLock;
    Lock* _stockRoomLock;
    int _stockBoyIdInStockRoom;
    int _stockBoysWaitingForStockRoomCV;
    Condition* _stockRoomCV;
    Lock* _stockBoyOrderLock;

    /*
     * Lock for Customer-StockBoy interaction
     * Used by customer to determine if a stock boy is in certain aisle
     */
    Lock* _stockBoysStatusLock;
    int _stockBoysStatus[MAX_STOCKBOYS]; // which Aisle we're in
    void SetStockBoysStatus(int stockBoyID, int newStatus);
    int GetStockBoysStatus(int stockBoyID);
    /*
     * Monitor for stock boys going on break and a manager waking them up
     */
    Lock* _stockBoyBreakLock;
    Condition* _stockBoysOnBreakCV;
    int _stockBoyOnBreakMV; //initial values set to zero
    /*
     * Monitor for Clerks going on break and a manager waking them up
     */
    Lock* _clerksOnBreakLock;
    Condition* _clerksOnBreakCV;
    int _clerksOnBreakMV; //initial values set to zero


    /*
     * Monitor for Clerks requesting more clerks to come off break
     */
    Lock* _signalManagerClerkHelp;
    bool _storeNeedsMoreClerks[MAX_CLERKS]; // false if lines are ok, true if a clerk saw a line > 4

    /*
     * Monitor for Customer waiting for a clerk coming back from break
     */
    Lock* _customerNeedsClerkAssitanceLock;
    Condition* _customerNeedsClerkAssitanceCV;
    Condition* _customerShouldFindTheClerkCV;
    int _customersNeedingAsistanceMV; //initial values set to zero
    int _clerkIDSignalingToCustomer;

    /*
     * Monitor for Manager giving money to cash Register
     */
    Lock* _registerNeedsMoney;
    Condition* _registerNeedsMoneyCV[MAX_CLERKS];
    double _moneyNeededForTill[MAX_CLERKS];
    double _moneyGivenToTill[MAX_CLERKS];
    int _registersThatNeedMoney;

    /*
     * Monitor for Customer-StockBoy interaction
     * Customers Waiting to ask the question
     */
    // NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS is the total number of lines that customers can form to ask
    // questions from stock boys. Customers first will try to find a stock boy in the aisles, if they
    // can not find any stock boy in any aisle they need to form a line in service area. That gives us
    // total number of MAX_AISLES + 1 lines. Which is defined as a macro in sharedDefinitions.
    Lock* _customersWaitingInAisleToAskQuestionLock[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];
    int _stockBoyIdInAisleToAnswerQuestionMV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];
    int _customersWaitingInAisleToAskQuestionMV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];
    Condition* _customersWaitingInAisleToAskQuestionCV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];

    /*
     * Monitor for Customer-StockBoy interaction
     * Customer handing item# to stock boy
     */
    Lock* _customerItemQuestionLock[MAX_STOCKBOYS];
	int _customerItemQuestionMV[MAX_STOCKBOYS];
	int _customerID_AskingQuestionMV[MAX_STOCKBOYS];
	Condition* _customerItemQuestionCV[MAX_STOCKBOYS];

	/*
	 * Monitor for Customer-StockBoy interaction
	 * Stock boy handing Aisle# to customer
	 */
	Lock* _stockBoyAisleAnswerLock[MAX_STOCKBOYS];
	int _stockBoyAisleAnswerMV[MAX_STOCKBOYS];
	Condition* _stockBoyAisleAnswerCV[MAX_STOCKBOYS];

	// Used for Customer getting in line and Clerks going on break
    Lock* _clerkLinelock;
    Condition* _clerkLineCV[MAX_CLERKS]; //CV for clerks
    int _clerkLineLength[MAX_CLERKS]; //Line length for each clerk
    ClerkStatus _clerkStatus[MAX_CLERKS]; //MV for clerks - 0 is at register, 1 is on break

    // Used in communication between customer and clerk
    Lock* _clerkLock[MAX_CLERKS];
    Condition* _clerkCV[MAX_CLERKS];
    Lock* _customerLock[MAX_CLERKS];
    Condition* _customerCV[MAX_CLERKS];
    Lock* _ItemPassingClerkLock[MAX_CLERKS];
    Condition* _ItemPassingClerkCV[MAX_CLERKS];
    int _nextItem[MAX_CLERKS]; // set to -1 for no more items

    /*
     * Three clerk/customer locks for passing money
     */
    Lock* _customerWaitForTotalLock[MAX_CLERKS];
    Condition* _customerWaitForTotalCV[MAX_CLERKS];
    Lock* _clerkWaitForMoneyLock[MAX_CLERKS];
    Condition* _clerkWaitForMoneyCV[MAX_CLERKS];
    Lock* _customerWaitForReceiptLock[MAX_CLERKS];
    Condition* _customerWaitForReceiptCV[MAX_CLERKS];
    Lock* _clerkWaitForCustomerLeavingLock[MAX_CLERKS];
    Condition* _clerkWaitForCustomerLeavingCV[MAX_CLERKS];
    double _orderTotal[MAX_CLERKS];
    double _ammountPaid[MAX_CLERKS];
    bool _receipt[MAX_CLERKS];
    int _customerBeingHelped[MAX_CLERKS]; // used for register to know what customer is being used

    // Clerk and Manager talking with Cash Registers
    Lock* _registerLock[MAX_CLERKS];
    Condition* _registerCV[MAX_CLERKS];
    Lock* _toRegisterInteractionLock[MAX_CLERKS];
    Condition* _toRegisterInteractionCV[MAX_CLERKS];
    Lock* _fromRegisterInteractionLock[MAX_CLERKS];
    Condition* _fromRegisterInteractionCV[MAX_CLERKS];
    int _clerkWantsToInteract[MAX_CLERKS]; //NEW
    int _managerWantsToInteract[MAX_CLERKS]; //NEW
    Item* _itemToScan[MAX_CLERKS];
    Item* _itemToRefund[MAX_CLERKS];
    double _moneyToTransfer[MAX_CLERKS];


    bool _requestingTotal[MAX_CLERKS];
    int _managerEmtpyingTill[MAX_CLERKS]; // -1 is free, 1 is with clerk, 2 is with managment
    int _peopleWaitingForCashRegister[MAX_CLERKS];
    Lock* _peopleWaitingForCashRegiterLock[MAX_CLERKS];
    Condition* _peopleWaitingForCashRegiterCV[MAX_CLERKS];
    /*
     * Monitor for knowing what a customer wants to do when they reach a clerk
     * each customer alters when they are sending their first item to a clerk
     */
    Lock* _customerActionLock;
    bool _customerWantsToScanItems[MAX_CLERKS]; // true if wanting to scan the item, false if return


    // Customer enters or leaves the store
    Lock* _occupancyLock;
    Condition* _storeDoorCV;
    int _customersInStore;


    //public:
    Locks();
    ~Locks();
    Lock* GetCustomersWaitingInAisleToAskQuestion(int aisleID);
    Lock* GetClerkCustomerCheckoutInteractionLock(int lineId);
    Lock* GetClerkManagerRegisterInteractionLock(int lineId);
    Lock* GetGlobalLineLock();
    //Lock* GlobalStockRoomLock();
    Lock* GetCustomerStockBoyItemInteractionLock(int itemNumber);
    //===> Added by peskanda
    /*
     * Lock for StockBoy-StockRoom interaction
     * Used by stock boys to make the stock room mutual exclusive
     */
    Lock* GetStockRoomLock();
    /*
     * Lock for Customer-StockBoy interaction
     * Used by customer to determine if a stock boy is in certain aisle
     */
    Lock* GetStockBoysStatusLock();
    /*
     * Monitor for Customer-StockBoy interaction
     * Customers Waiting to ask the question
     */
    Lock* GetCustomersWaitingInAisleToAskQuestionLock(int aisleNumber);
    int* GetCustomersWaitingInAisleToAskQuestionMV(int aisleNumber); //NOTE: Please notice this should return a pointer since we need to modify its content
    Condition* GetCustomersWaitingInAisleToAskQuestionCV(int AisleNumber);
    /*
     * Monitor for Customer-StockBoy interaction
     * Customer handing item# to stock boy
     */
    Lock* GetCustomerItemQuestionLock(int stockBoyIndex);
    int* GetCustomerItemQuestionMV(int stockBoyIndex); //NOTE: Please notice this should return a pointer since we need to modify its content
    Condition* GetCustomerItemQuestionCV(int stockBoyIndex);
    /*
     * Monitor for Customer-StockBoy interaction
     * Stock boy handing Aisle# to customer
     */
    Lock* GetStockBoyAisleAnswerLock(int stockBoyIndex);
    int* GetStockBoyAisleAnswerMV(int stockBoyIndex); //NOTE: Please notice this should return a pointer since we need to modify its content
    Condition* GetStockBoyAisleAnswerCV(int stockBoyIndex);
    //<=== End of the changes by peskanda
    Condition* GetClerksOnBreakCV();
    Condition* GetStockBoysOnBreakCV();
    Condition* GetClerkCustomerItemTransferCV(int lineId);

    Item* GetSharedClerkCustomerItem(int lineId);
};

#endif /* LOCKS_H_ */
